import Snake from './Snake';
import Food from './Food';
import ScorePanel from './ScorePanel';
import Key from './Key';
class GameControl {
    snake: Snake;
    food: Food;
    scorePanel: ScorePanel;
    key: Key;
    start = false;
    onKeybord = false;
    constructor() {
        this.snake = new Snake();
        this.food = new Food();
        this.scorePanel = new ScorePanel();
        this.key = new Key(this.keyDownHandler.bind(this));
        document.addEventListener('keydown', this.keyDownHandler.bind(this));/* 事件绑定给哪个元素this就是那个元素，bind创建新的作用域 */
    }

    // 监听按键
    keyDownHandler(event: KeyboardEvent) {
        this.key.keydownShow(event);
        if (event.keyCode == 32) {
            this.gameStart();
        } else {
            this.changeDirection(event);
        }
    }

    // 初始化
    init() {
        this.scorePanel.init();
        this.snake.init();
        this.start = true;
    }

    // 开始游戏
    gameStart() {
        if (!this.start) {
            this.init();
            this.run(this.scorePanel.speed);
        } else {
            console.log("正在游戏中");
        }
    }

    // 移动
    run(speed: number) {
        let XY = this.computeNextXY();
        if (!this.isOutRange(XY) && this.start) {
            if (this.isContact(XY[0], XY[1])) {
                this.snake.addBody();
                this.food.change();
                this.scorePanel.addScore();
            }
            this.snake.moveBody();
            this.snake.XY = [XY[0], XY[1]];
            this.onKeybord = true;
            setTimeout(() => {
                this.run(this.scorePanel.speed)
            }, this.scorePanel.speed);
        } else {
            this.start = false;
            this.snake.life = false;
            console.log('game over');
        }
    }

    // 计算下一步位置
    computeNextXY(): number[] {
        let x = this.snake.X;
        let y = this.snake.Y;
        switch (this.snake.direction) {
            case 'left':
                x -= 10;
                break;
            case 'up':
                y -= 10;
                break;
            case 'right':
                x += 10;
                break;
            case 'down':
                y += 10;
                break;
        }
        return [x, y];
    }

    isOutRange(headXY: number[]): boolean {
        function hitWall(): boolean {
            if (headXY[0] <= 290 && headXY[0] >= 0 && headXY[1] <= 290 && headXY[1] >= 0) {
                return false;
            } else {
                return true;
            }
        }
        function hitBody(): boolean {
            let bodyXY = this.snake.bodyXY;
            for (let i = 0; i < bodyXY.length; i++) {
                const element = bodyXY[i];
                if (JSON.stringify(element) == JSON.stringify(headXY)) {
                    return true;
                }
            }
            if (bodyXY.length > 5) {
                let a = 1;
            }
            return false;
        }
        if (!hitWall.bind(this)() && !hitBody.bind(this)()) {
            return false;
        }
        return true;
    }

    // 改变方向
    changeDirection(event: KeyboardEvent) {
        if (!this.onKeybord) {
            console.log("change invalid");
            return;
        }
        this.onKeybord = false;
        if (event.keyCode >= 37 && event.keyCode <= 40) {
            let key = "";
            switch (event.keyCode) {
                case 37:
                    key = this.snake.direction == "right" && this.snake.length != 1 ? "right" : "left";
                    break;
                case 38:
                    key = this.snake.direction == "down" && this.snake.length != 1 ? "down" : "up";
                    break;
                case 39:
                    key = this.snake.direction == "left" && this.snake.length != 1 ? "left" : "right";
                    break;
                case 40:
                    key = this.snake.direction == "up" && this.snake.length != 1 ? "up" : "down";
                    break;
            }
            this.snake.direction = key;
        }
    }

    // 检测是否吃到食物
    isContact(x: number, y: number) {
        if (x == this.food.X && y == this.food.Y) {
            return true;
        } else {
            return false;
        }
    }


}
export default GameControl;